package com.jichangxiu.dynamic.test.config;

import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.text.MessageFormat;

/**
 * @author Jcx
 * @date 2022/11/27 7:52
 */
@Order(3)
@Slf4j
@Aspect
@Component
public class SelectDbAspect {

    @Value("${jcx.db.url}")
    private String url;
    @Value("${jcx.db.username}")
    private String username;
    @Value("${jcx.db.password}")
    private String password;

    @Pointcut("@within(com.jichangxiu.dynamic.test.config.SelectDB)"
            + "|| @annotation(com.jichangxiu.dynamic.test.config.SelectDB)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 获取类名
        // String className = point.getTarget().getClass().getSimpleName();
        // 获取方法名
        // String methodName = point.getSignature().getName();
        // 获取参数列表
        // Object[] args = point.getArgs();
        // 获取参数类型列表
        // Class<?>[] par = ((MethodSignature) point.getSignature()).getParameterTypes();
        // 获取方法对象
        // Method objMethod = classTarget.getMethod(methodName, par);
        Class<?> classTarget = point.getTarget().getClass();
        // 获取类上的 SelectDB 注解
        SelectDB annotation = classTarget.getAnnotation(SelectDB.class);
        if (ObjectUtil.isEmpty(annotation)) {
            // 获取方法上 SelectDB 注解
            MethodSignature methodSignature = (MethodSignature) point.getSignature();
            Method method = methodSignature.getMethod();
            annotation = method.getAnnotation(SelectDB.class);
        }
        String dbName = DynamicDataSource.DEFAULT_DB_KEY;
        String serverFiled = "-1";
        if (ObjectUtil.isNotEmpty(annotation)) {
            dbName = annotation.dbName();
            serverFiled = annotation.serverFiled();
        }
        if ("-1".equals(serverFiled)) {
            // 切换到对应的库，不区分区服的库
            DynamicDataSourceService.switchDb(dbName);
        } else {
            // 切换到对应的库，根据区服切换到不同的库
            Object[] strArr = AnalyzeParamsUtils.analyzeParams(point, serverFiled);
            dbName = MessageFormat.format(dbName, strArr);
            boolean exist = DynamicDataSourceService.exist(dbName);
            if (exist) {
                DynamicDataSourceService.switchDb(dbName);
            } else {
                // 确保开启新的区服后会新增game_x_data,game_x_log两个库，也能够正常查询
                String urlFormat = MessageFormat.format(url, dbName);
                DynamicDataSourceService.addDataSource(dbName, urlFormat, username, password);
                DynamicDataSourceService.switchDb(dbName);
            }
        }
        Object proceed = point.proceed();
        DynamicDataSourceService.resetDb();
        return proceed;
    }
}

